package com.example.components.service.impl;

import com.example.components.exception.BaseAppException;
import com.example.components.mapper.AlarmRuleDoMapper;
import com.example.components.model.AlarmRuleDo;
import com.example.components.model.AlarmRuleDoExample;
import com.example.components.model.Group;
import com.example.components.model.PrometheusRule;
import com.example.components.model.Rule;
import com.example.components.service.AlarmRuleService;
import com.example.components.utils.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.representer.Representer;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Auther: Jason
 * @Date: 2022/4/11 16:05
 * @Description:
 */
@Service
public class AlarmRuleRuleServiceImpl implements AlarmRuleService {

    public static final Logger logger = LoggerFactory.getLogger(AlarmRuleRuleServiceImpl.class);

    @Autowired
    private AlarmRuleDoMapper alarmRuleDoMapper;

    private static DumperOptions dumperOptions = new DumperOptions();

    static {
        //设置yaml读取方式为块读取
        dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        dumperOptions.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN);
        dumperOptions.setPrettyFlow(false);
    }

    @Override
    public List<AlarmRuleDo> queryAlarmRuleList(Integer resourceType) throws BaseAppException{
        logger.info("AlarmRuleRuleServiceImpl queryAlarmRuleList start");
        AlarmRuleDoExample alarmRuleDoExample = new AlarmRuleDoExample();
        AlarmRuleDoExample.Criteria criteria = alarmRuleDoExample.createCriteria();
        criteria.andTypeEqualTo(resourceType);
        List<AlarmRuleDo> alarmRuleDoList = alarmRuleDoMapper.selectByExample(alarmRuleDoExample);
        return alarmRuleDoList;
    }

    private String getAlarmLevel(Integer level) {
        String levelStr;
        if (level == 1) {
            levelStr = "critical";
        }
        else if (level == 2){
            levelStr = "major";
        }
        else {
            levelStr = "info";
        }
        return levelStr;
    }

    @Override
    public void syncAlarmRule(Integer resourceType)  throws BaseAppException{
        logger.info("AlarmRuleRuleServiceImpl syncAlarmRule start");
        try {
            List<AlarmRuleDo> alarmRuleDoList = queryAlarmRuleList(resourceType);
            String srcFilePath = System.getProperty("user.dir") + "/src/main/resources/prometheus/rules/node_exporter-rule-src.yaml";
          String desFilePath = System.getProperty("user.dir") + "/src/main/resources/prometheus/rules/node_exporter-rule5.yaml";
//            String desFilePath ="/etc/prometheus/node_exporter-rule.yaml";
            List<Rule> ruleList = new ArrayList<>();
            for (AlarmRuleDo alarmRuleDo : alarmRuleDoList) {
                Rule rule = new Rule();
                Map<String, String> lableMap = new HashMap<>();
                lableMap.put("status", alarmRuleDo.getStatus());
                String level = getAlarmLevel(alarmRuleDo.getLevel());
                lableMap.put("level", level);
                Map<String, String> annotationsMap = new HashMap<>();
                annotationsMap.put("summary", alarmRuleDo.getSummary());
                annotationsMap.put("description", alarmRuleDo.getDescription());
                rule.setAlert(alarmRuleDo.getAlert());
                rule.setForName(alarmRuleDo.getForTime());
                rule.setExpr(alarmRuleDo.getExpr());
                rule.setLabels(lableMap);
                rule.setAnnotations(annotationsMap);
                ruleList.add(rule);
            }
            Group group = new Group();
            group.setName("主机告警策略");
            group.setRules(ruleList);
            List<Group> groupList = new ArrayList<>();
            groupList.add(group);
            PrometheusRule prometheusRule = new PrometheusRule(groupList);
            // 有 Yaml 中存在，Bean 不存在的属性时，反序列化会报错，可以使用 Representer 设置忽略不存在的属性解决这个问题
            Representer representer = new Representer();
            representer.getPropertyUtils().setSkipMissingProperties(true);
            Yaml yaml = new Yaml(new Constructor(PrometheusRule.class), representer, dumperOptions);
            FileUtils.createFile(srcFilePath);
            yaml.dump(prometheusRule, new FileWriter(srcFilePath));
            FileUtils.translateFileInfo2(srcFilePath, desFilePath);
            FileUtils.clearInfoForFile(srcFilePath);
            // prometheus 规则热加载
            // todo
        } catch (BaseAppException e) {
            logger.error(e.getMessage());
        }catch (IOException e) {
            logger.error(e.getMessage());
        }
    }

}
